package cn.topevery.garden.dal.dao.impl;

import cn.topevery.garden.dal.dao.PersonDao;
import cn.topevery.garden.entity.po.Person;
import cn.topevery.garden.entity.po.PersonSearch;
import cn.topevery.garden.entity.query.PersonQuery;
import cn.topevery.garden.entity.vo.PersonVO;
import cn.topevery.garden.entity.vo.oneMap.CountVO;
import cn.topevery.garden.framework.base.BaseDaoImpl;
import hw.topevery.basis.entity.po.SysUser;
import hw.topevery.framework.db.CommandType;
import hw.topevery.framework.db.entity.DataPager;
import hw.topevery.framework.db.entity.SqlQueryMate;
import hw.topevery.framework.db.enums.ScriptConditionEnum;
import hw.topevery.framework.entity.DbCsp;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 描述 The type Person dao.
 *
 * @author code -generate
 * @created 2021 -09-09 13:47:26
 * @date 2021 -08-06
 */
@Repository
public class PersonDaoImpl extends BaseDaoImpl<Person> implements PersonDao {
    /**
     * 描述 Gets search.
     *
     * @param <P>  the type parameter
     * @param para the para
     * @return the search
     * @author wenzhao.lin
     * @created 2021 -09-09 13:47:26
     */
    @Override
    public <P extends DbCsp> List<Person> getSearch(P para) {
        return null;
    }


    /**
     * 描述 获取列表.
     *
     * @param query the query
     * @return the data pager
     * @author wenzhao.lin
     * @created 2021 -09-09 13:47:26 List page data pager.
     */
    @Override
    public DataPager<PersonSearch> listPage(PersonQuery query) {
        String table = "t_person tp " +
                "left join t_sys_user tsu on tp.c_user_id=tsu.c_user_id " +
                "left join t_task_info ta on ta.c_id = tp.c_task_id " +
                "left join t_dingtalk_duty du on du.c_id = tp.c_shift_id ";

        String columns = "tp.*,tsu.c_dept_id,tsu.c_user_idcard,ta.c_name taskName,du.c_name shiftName ";
        int pageIndex = query.pageIndex - 1;
        int pageSize = query.pageSize;

        SqlQueryMate sqlQueryMate = new SqlQueryMate(table).setColumns(columns).setOrderBy("tp.c_db_create_date desc");
        sqlQueryMate
                .where(true, "tp.c_db_status", ScriptConditionEnum.Eq, 0)
                .where(StringUtils.isNotBlank(query.getName()), "tp.c_name", ScriptConditionEnum.Like, query.getName())
                .where(StringUtils.isNotBlank(query.getCode()), "tsu.c_user_idcard", ScriptConditionEnum.Like, query.getCode())
                .where(query.getStatus() != null, "tp.c_work_state", ScriptConditionEnum.Eq, query.getStatus())
                .where(query.getParkId() != null, "tp.c_park_id", ScriptConditionEnum.Eq, query.getParkId())
                .where(query.getSectionId() != null, "tp.c_section_id", ScriptConditionEnum.Eq, query.getSectionId())
                .where(query.getExtentId() != null, "tp.c_extent_id", ScriptConditionEnum.Eq, query.getExtentId())
                .where(query.getTaskId() != null, "tp.c_task_id", ScriptConditionEnum.Eq, query.getTaskId())
                .where(query.getShiftId() != null, "tp.c_shift_id", ScriptConditionEnum.Eq, query.getShiftId())
                .where(StringUtils.isNotBlank(query.getDeptId()), "tsu.c_dept_id", ScriptConditionEnum.Eq, query.getDeptId())

        ;

        return getDataPager(sqlQueryMate, pageSize, pageIndex, PersonSearch.class);
    }


    /**
     * 描述 获取统计数量
     *
     * @param name     the name
     * @param extentId the extent id
     * @param typeId   the type id
     * @return the count
     * @author wenzhao.lin
     * @created 2021 -08-25 09:24:05
     */
    @Override
    public Map getCount(String name, Integer extentId, Integer typeId) {
        String table = "t_person tp";

        String columns = "count(1) value,'人员总数' as name";

        SqlQueryMate sqlQueryMate = new SqlQueryMate(table).setColumns(columns);
        sqlQueryMate
                .where(true, "tp.c_db_status", ScriptConditionEnum.Eq, 0)
                .where(StringUtils.isNotBlank(name), "tp.c_name", ScriptConditionEnum.Like, name)
                .where(extentId != null, "tp.c_section_id", ScriptConditionEnum.Eq, extentId)
                .where(typeId != null, "tp.c_type", ScriptConditionEnum.Eq, typeId)
        ;
        return getOneMap(sqlQueryMate);
    }

    /**
     * 描述 通过人员类型获取列表
     *
     * @param name       the name
     * @param extentId   the extent id
     * @param personType the person type
     * @return the person list by type
     * @author wenzhao.lin
     * @created 2021 -08-25 09:25:36
     */
    @Override
    public List<Person> getPersonListByType(String name, Integer extentId, Integer personType) {
        String table = "t_person tp";

        String columns = "tp.*";

        SqlQueryMate sqlQueryMate = new SqlQueryMate(table).setColumns(columns);
        sqlQueryMate
                .where(true, "tp.c_db_status", ScriptConditionEnum.Eq, 0)
                .where(StringUtils.isNotBlank(name), "tp.c_name", ScriptConditionEnum.Like, name)
                .where(extentId != null, "tp.c_extent_id", ScriptConditionEnum.Eq, extentId)
                .where(personType != null, "tp.c_type", ScriptConditionEnum.Eq, personType)
        ;
        return selectList(sqlQueryMate, Person.class);
    }

    /**
     * 描述 获取类型列表
     *
     * @param name     the name
     * @param extentId the extent id
     * @return the person type list
     * @author wenzhao.lin
     * @created 2021 -08-27 09:15:52
     */
    @Override
    public List<Person> getPersonTypeList(String name, Integer extentId) {
        String table = "t_person tp";

        String columns = "distinct tp.c_type, tp.c_type_name";

        SqlQueryMate sqlQueryMate = new SqlQueryMate(table).setColumns(columns);
        sqlQueryMate
                .where(true, "tp.c_db_status", ScriptConditionEnum.Eq, 0)
                .where(StringUtils.isNotBlank(name), "tp.c_name", ScriptConditionEnum.Like, name)
                .where(extentId != null, "tp.c_section_id", ScriptConditionEnum.Eq, extentId)
        ;

        List<Person> list = selectList(sqlQueryMate, Person.class);

        for (Person person : list) {
            if (person.getType() != null) {
                Map temp = getCount(name, extentId, person.getType());
                person.setTotalNumber(String.valueOf(temp.get("value")));
            }
        }

        return list;
    }

    /**
     * 描述 Gets sys user list.
     *
     * @param mobiles the mobiles
     * @return the sys user list
     * @author wenzhao.lin
     * @created 2021 -09-09 13:47:26
     */
    @Override
    public List<SysUser> getSysUserList(List<String> mobiles) {
        String table = "t_person tp join t_sys_user tsu on tp.c_user_id=tsu.c_user_id";

        String columns = "tsu.*";

        SqlQueryMate sqlQueryMate = new SqlQueryMate(table).setColumns(columns);
        sqlQueryMate
                .where(true, "tsu.c_db_status", ScriptConditionEnum.Eq, 0)
                .where(true, "tsu.c_user_mobile", ScriptConditionEnum.In, mobiles)
        ;
        return selectList(sqlQueryMate, SysUser.class);
    }

    /**
     * 描述 Gets peson list.
     *
     * @param mobiles the mobiles
     * @return the peson list
     * @author wenzhao.lin
     * @created 2021 -09-09 13:47:26
     */
    @Override
    public List<Person> getPesonList(List<String> mobiles) {
        String table = "t_person tp join t_sys_user tsu on tp.c_user_id=tsu.c_user_id";

        String columns = "tp.*";

        SqlQueryMate sqlQueryMate = new SqlQueryMate(table).setColumns(columns);
        sqlQueryMate
                .where(true, "tsu.c_db_status", ScriptConditionEnum.Eq, 0)
                .where(true, "tsu.c_user_mobile", ScriptConditionEnum.In, mobiles)
        ;
        return selectList(sqlQueryMate, Person.class);
    }

    /**
     * 描述 一张图管理-人车概况- 获取人员统计
     *
     * @return the type count
     * @author wenzhao.lin
     * @created 2021 -09-07 16:54:23
     */
    @Override
    public List<CountVO> getPersonCount() {
        StringBuffer sb = new StringBuffer();
        sb.append("select count(1) value, '人员总数' name,'人' from t_person tp join t_device_object_relate tdor on tp.c_id=tdor.c_object_id where tdor.c_object_type=0 and tdor.c_db_status=0  and tp.c_db_status=0 " +
                "union all " +
                "select count(1) value, '当班人数' name,'人' unit from t_curr_status_people t " +
                "inner join t_person p on p.c_user_id = t.c_user_id " +
                "where t.c_db_status=0 and t.c_online_type =1 and p.c_db_status=0");

        AtomicReference<List<CountVO>> vo = new AtomicReference<>(new ArrayList<>());
        run(sb.toString(), CommandType.Text, dbCommand -> {
            vo.set(dbCommand.executeToList(CountVO.class));
        });

        return vo.get();
    }

    /**
     * 描述 一张图管理-人车概况- 获取人员 在线/离线 统计
     *
     * @return the person online count
     * @author wenzhao.lin
     * @created 2021 -09-13 09:19:32
     */
    @Override
    public List<CountVO> getPersonOnlineAndOutCount() {
        StringBuffer sb = new StringBuffer();
        sb.append("select count(1) value, '在线' name,'人' unit from t_curr_status_people t  " +
                "                inner join t_person p on p.c_user_id = t.c_user_id  " +
                "                where t.c_db_status=0 and t.c_online_type =1 and p.c_db_status=0 " +
                "union all " +
                "select count(1) value, '离线' name,'人' unit from t_curr_status_people t  " +
                "                inner join t_person p on p.c_user_id = t.c_user_id  " +
                "                where t.c_db_status=0 and t.c_online_type =0 and p.c_db_status=0");

        AtomicReference<List<CountVO>> vo = new AtomicReference<>(new ArrayList<>());
        run(sb.toString(), CommandType.Text, dbCommand -> {
            vo.set(dbCommand.executeToList(CountVO.class));
        });

        return vo.get();
    }

    /**
     * 描述 一张图管理-人车概况- 获取所有人员类型统计
     *
     * @return the type count
     * @author wenzhao.lin
     * @created 2021 -09-07 16:54:23
     */
    @Override
    public List<CountVO> getPersonTypeCount() {
        StringBuffer sb = new StringBuffer();
        sb.append("select count(1) value,tp.c_type_name name,'人' unit from t_person tp join t_device_object_relate tdor on tp.c_id=tdor.c_object_id where tdor.c_object_type=0 and tdor.c_db_status=0  and tp.c_db_status=0  and tp.c_type_name is not null group by tp.c_type_name order by value desc");

        AtomicReference<List<CountVO>> vo = new AtomicReference<>(new ArrayList<>());
        run(sb.toString(), CommandType.Text, dbCommand -> {
            vo.set(dbCommand.executeToList(CountVO.class));
        });

        return vo.get();
    }

    /**
     * 描述 一张图管理-人车概况- 获取在岗人员类型统计
     *
     * @return the type count
     * @author wenzhao.lin
     * @created 2021 -09-07 16:54:23
     */
    @Override
    public List<CountVO> getPersonOnlineCount() {
        StringBuffer sb = new StringBuffer();
        sb.append("select count(1) value,p.c_type_name name,'人' unit from t_curr_status_people t " +
                "inner join t_person p on p.c_user_id = t.c_user_id " +
                "where t.c_db_status=0 and t.c_online_type =1 and p.c_db_status=0 group by p.c_type_name order by value desc");

        AtomicReference<List<CountVO>> vo = new AtomicReference<>(new ArrayList<>());
        run(sb.toString(), CommandType.Text, dbCommand -> {
            vo.set(dbCommand.executeToList(CountVO.class));
        });

        return vo.get();
    }

    /**
     * 描述 一张图管理-人车概况- 获取人员列表
     *
     * @param query the query
     * @return the data pager
     * @author wenzhao.lin
     * @created 2021 -09-09 13:47:26 List page data pager.
     */
    @Override
    public DataPager<PersonVO> getPersonListData(PersonQuery query) {
        String table = "t_person p join t_curr_status_people t on t.c_user_id = p.c_user_id " +
                " left join t_sys_user su on su.c_user_id = p.c_user_id ";

        String columns = "p.*," +
                "t.c_geo_x,t.c_geo_y,t.c_gps_id,t.c_client_key,t.c_online_type,t.c_online_time,t.c_valid_time,t.c_valid_mileage," +
                "su.c_user_birthday,su.c_user_mobile c_user_telephone,su.c_user_sex";
        int pageIndex = query.pageIndex - 1;
        int pageSize = query.pageSize;

        SqlQueryMate sqlQueryMate = new SqlQueryMate(table).setColumns(columns).setOrderBy("t.c_online_type desc");
        sqlQueryMate
                .where(true, "p.c_db_status", ScriptConditionEnum.Eq, 0)
                .where(query.getType() != null && query.getType() == 1, "t.c_online_type", ScriptConditionEnum.Eq, query.getType())
                .where(StringUtils.isNotBlank(query.getName()), "p.c_name", ScriptConditionEnum.Like, query.getName())
                .where(StringUtils.isNotBlank(query.getCode()), "p.c_user_idcard", ScriptConditionEnum.Like, query.getCode())
                .where(query.getStatus() != null, "p.c_work_state", ScriptConditionEnum.Eq, query.getStatus())
                .where(query.getParkId() != null, "p.c_park_id", ScriptConditionEnum.Eq, query.getParkId())
                .where(query.getSectionId() != null, "p.c_section_id", ScriptConditionEnum.Eq, query.getSectionId())
                .where(query.getExtentId() != null, "p.c_extent_id", ScriptConditionEnum.Eq, query.getExtentId())
        ;

        return getDataPager(sqlQueryMate, pageSize, pageIndex, PersonVO.class);
    }

    @Override
    public PersonVO getByUserId(String userId) {
        String table = "t_person tp";

        String columns = "tp.*";

        SqlQueryMate sqlQueryMate = new SqlQueryMate(table).setColumns(columns);
        sqlQueryMate
                .where(true, "tp.c_db_status", ScriptConditionEnum.Eq, 0)
                .where(true, "tp.c_user_id", ScriptConditionEnum.Eq, userId);
        AtomicReference<PersonVO> person = new AtomicReference<>(new PersonVO());
        run(sqlQueryMate.getSql(), CommandType.Text, dbCommand -> {
            sqlQueryMate.getParameters().forEach(dbCommand::addParameter);
            person.set(dbCommand.executeToEntity(PersonVO.class));
        });
        return person.get();
    }

    @Override
    public List<Map<String, Object>> getOpenIdByExtentId(Integer extentId) {
        String sql = "select t1.c_wx_ma_openid from t_person t left join t_sys_user t1 on t.c_user_id = t1.c_user_id where t.c_db_status = 0 and t.c_extent_id = :p_extent_id and t1.c_wx_ma_openid is not null";
        run(sql, CommandType.Text, dbCommand -> {
            dbCommand.addInParameter("p_extent_id", extentId);
            dbCommand.executeToList(String.class);
        });
        String table = "t_person t left join t_sys_user t1 on t.c_user_id = t1.c_user_id";

        String columns = "t1.c_wx_ma_openid";

        SqlQueryMate sqlQueryMate = new SqlQueryMate(table).setColumns(columns);
        sqlQueryMate
                .where(true, "t.c_db_status", ScriptConditionEnum.Eq, 0)
                .where(true, "t.c_extent_id", ScriptConditionEnum.Eq, extentId)
                .where(true, "t1.c_wx_ma_openid", ScriptConditionEnum.NotEq, null);
        return getMap(sqlQueryMate);
    }

    @Override
    public List<SysUser> getUserNotIn() {
        String sql = "SELECT * FROM `t_sys_user` tsu \n" +
                "WHERE tsu.c_db_status = 0 \n" +
                " AND tsu.c_user_id NOT IN (\n" +
                " SELECT\n" +
                "  tp.c_user_id \n" +
                " FROM\n" +
                "  t_person tp \n" +
                "WHERE\n" +
                " tp.c_db_status = 0)";
        return getList(sql, CommandType.Text, Collections.emptyList(), SysUser.class);
    }
}
